#include <string>
#include "Messanger.h"

Messanger::Messanger(const string * sJID, const string * pass, const string * dJID)
{
	this->sJID = new string(*sJID);
	this->pass = new string(*pass);
	this->dJID = new string(*dJID);
	
    JID jid(*this->sJID);
    j = new Client(jid, *this->pass);
	
    j->setXmlLang("UTF-8");
    j->registerMessageHandler(this);
    j->setPresence(PresenceAvailable, 5);
	j->registerConnectionListener(this);
	
	shutdown = false;
	pthread_mutex_init(&shutdown_mut, NULL);

	ping_counter = 0;
	pthread_create(&ping_thread, NULL, &Messanger::start_ping_thread, this);
}

Messanger::~Messanger()
{
	pthread_mutex_lock(&shutdown_mut);
	shutdown = true;
	pthread_mutex_unlock(&shutdown_mut);
	
	pthread_join(ping_thread, NULL);
    this->disconnect();
}

void Messanger::connect()
{
	this->disconnect();
	
	if (j->connect(false)) {
		bool auth_success = false;
		bool auth_error   = false;

		while (!auth_success && !auth_error) {
			j->recv(1);
			auth_success = j->authed();
			auth_error   = j->authError() != AuthErrorUndefined;
		}
	}
}

void Messanger::disconnect()
{
    j->disconnect();
}

void Messanger::send(string &msg)
{
    JID to(*this->dJID);
    Stanza *s = Stanza::createMessageStanza(to, msg);
    j->send(s);
}

bool Messanger::isConnected()
{
	return j->state() == StateConnected;
}

bool Messanger::isAuthenticated()
{
	return j->authed();
}

bool Messanger::test(const string * user, const string * pass)
{
	bool success = false;
	
	/* Create client */
    const JID jid(*user);
	string pass2(*pass);
    Client * c = new Client(jid, pass2);
    c->setXmlLang("UTF-8");
    c->setPresence(PresenceAvailable, 5);
	
	/* Try to connect and authenticate */
	if (c->connect(false)) {
		bool auth_success = false;
		bool auth_error   = false;

		while (!auth_success && !auth_error) {
			c->recv();
			auth_success = c->authed();
			auth_error   = c->authError() != AuthErrorUndefined;
		}
			
		c->disconnect();
		success = auth_success ? true : false;
	}
	delete c;
	
	return success;
}

void Messanger::doPing()
{
	while (true) {
		/* Close down? */
		bool die = false;
		pthread_mutex_lock(&shutdown_mut);
		if (shutdown == true) {
			die = true;
		}
		pthread_mutex_unlock(&shutdown_mut);

		if (die == true) {
			pthread_exit(NULL);
		}
		
		/* Take a nap */
		if (this->isConnected()) {
			j->recv(200000);
		}
		else {
			usleep(200000);
		}
		
		ping_counter++;
		
		/* Now ping... for real... */
		if (ping_counter == 150) {
			ping_counter = 0;
			j->whitespacePing();
		}
	}
}

void Messanger::handleMessage(Stanza* stanza, MessageSession* session = 0)
{

}

void Messanger::onConnect() {
}

void Messanger::onDisconnect(ConnectionError e) {
}

bool Messanger::onTLSConnect(const CertInfo &info) {
	return false;
}

void * Messanger::start_ping_thread(void *obj)
{
	reinterpret_cast<Messanger *>(obj)->doPing();
	
	return NULL;
}




